package myself.study.network.tcp.examples.ex01;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import org.junit.Test;

/**
* @Name: TcpClient
* @Description: 案例一：客户端键盘录入请求数据
* 使用到的类：BufferedReader、BufferedWriter、InputStreamReader、OutputStreamWriter
* 说明：
* 	BufferedReader类：从字符输入流中读取文本，缓冲各个字符，从而实现字符、数组和行的高效读取。 
* 					 通常，Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。
* 					 因此，建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader（如 FileReader 和 InputStreamReader）。
* 					 将缓冲指定文件的输入。如果没有缓冲，则每次调用 read() 或 readLine() 都会导致从文件中读取字节，并将其转换为字符后返回，而这是极其低效的。 
*  					 通过用合适的 BufferedReader 替代每个 DataInputStream，可以对将 DataInputStream 用于文字输入的程序进行本地化。 
* 		BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
* 		public String readLine() 读取一个文本行。通过下列字符之一即可认为某行已终止：换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。 
* 								   返回包含该行内容的字符串，不包含任何行终止符，如果已到达流末尾，则返回 null。
* 		public void close() 关闭该流并释放与之关联的所有资源。
* 	InputStreamReader类： InputStreamReader 是字节流通向字符流的桥梁：它使用指定的 charset 读取字节并将其解码为字符。
* 						它使用的字符集可以由名称指定或显式给定，或者可以接受平台默认的字符集。 
* 						为了达到最高效率，可要考虑在 BufferedReader 内包装 InputStreamReader。
* 						BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
* 		InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。
* 		InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader。
* 		public String getEncoding() 返回此流使用的字符编码的名称。 
* 	BufferedWriter类：将文本写入字符输出流，缓冲各个字符，从而提供单个字符、数组和字符串的高效写入。 
* 					 该类提供了 newLine() 方法，调用此方法来终止每个输出行要优于直接写入新行符。
* 					 通常 Writer 将其输出立即发送到底层字符或字节流。
* 					 除非要求提示输出，否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer（如 FileWriters 和 OutputStreamWriters）。
* 					 将缓冲 PrintWriter 对文件的输出。如果没有缓冲，则每次调用 print() 方法会导致将字符转换为字节，然后立即写入到文件，而这是极其低效的。 
* 		BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。
* 		public void write(int c) 写入单个字符。 
* 		public void newLine() 写入一个行分隔符。
* 		public void flush() 刷新该流的缓冲。 
* 		public void close() 关闭此流，但要先刷新它。
* 	OutputStreamWriter类：OutputStreamWriter 是字符流通向字节流的桥梁：可使用指定的 charset 将要写入流中的字符编码成字节。
* 						  它使用的字符集可以由名称指定或显式给定，否则将接受平台默认的字符集。 
* 						  为了获得最高效率，可考虑将 OutputStreamWriter 包装到 BufferedWriter 中，以避免频繁调用转换器。例如：
* 						 Writer out  = new BufferedWriter(new OutputStreamWriter(System.out));
* 		OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。
* 		OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter。
* 		public String getEncoding() 返回此流使用的字符编码的名称。 
* 		public void write(int c) 写入单个字符。 
* 		public void flush() 刷新该流的缓冲。 
* 		public void close() 关闭此流，但要先刷新它。
* @Author: 李超	lc_jack@foxmail.com
* @CreateDate: 2017-1-12 下午2:05:58 
* @Version: V1.0
 */
public class TcpClient {

	@Test
	public void keyWordInputData() throws UnknownHostException, IOException {
		//获取客户端Socket对象
		Socket client = new Socket("127.0.0.1", 12345) ;
		//键盘录入数据，放入到高效字符输入流
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)) ;
		//把通道内的输出流包装成高效字符输出流
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())) ;
		String line = null ;
		while((line = reader.readLine()) != null) {
			//输入'over'，结束键盘输入
			if("over".equals(line)) {
				break ;
			}
			//将键盘录入的数据发送到服务端
			writer.write(line) ;
			//写入一个行分隔符
			writer.newLine() ;
			//刷新该流的缓冲。
			writer.flush() ;
		}
		//释放资源
		//writer.close() ; //Socket对象关闭后，BufferedWriter对象将自动关闭
		//reader.close() ; //结束键盘输入后，该BufferedReader对象将自动关闭
		client.close() ;
	}
	
}
